// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.fileSystem;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import zombie.core.logger.ExceptionLogger;

public final class DiskFileDevice implements IFileDevice {
    private final String m_name;

    public DiskFileDevice(String name) {
        this.m_name = name;
    }

    @Override
    public IFile createFile(IFile child) {
        return new DiskFileDevice.DiskFile(child, this);
    }

    @Override
    public void destroyFile(IFile file) {
    }

    @Override
    public InputStream createStream(String path, InputStream child) throws IOException {
        return new FileInputStream(path);
    }

    @Override
    public void destroyStream(InputStream stream) {
    }

    @Override
    public String name() {
        return this.m_name;
    }

    private static final class DiskFile implements IFile {
        final DiskFileDevice m_device;
        RandomAccessFile m_file;
        InputStream m_inputStream;
        final IFile m_fallthrough;
        boolean m_use_fallthrough;

        DiskFile(IFile iFile, DiskFileDevice diskFileDevice) {
            this.m_device = diskFileDevice;
            this.m_fallthrough = iFile;
            this.m_use_fallthrough = false;
        }

        @Override
        public boolean open(String string, int _int) {
            File file = new File(string);
            boolean _boolean = (_int & 1) != 0;
            if (_boolean && !file.exists() && this.m_fallthrough != null) {
                this.m_use_fallthrough = true;
                return this.m_fallthrough.open(string, _int);
            } else {
                try {
                    if ((_int & 16) == 0) {
                        this.m_file = new RandomAccessFile(string, FileOpenMode.toStringMode(_int));
                    } else {
                        this.m_inputStream = new FileInputStream(string);
                    }

                    return true;
                } catch (IOException iOException) {
                    ExceptionLogger.logException(iOException);
                    return false;
                }
            }
        }

        @Override
        public void close() {
            if (this.m_fallthrough != null) {
                this.m_fallthrough.close();
            }

            if (this.m_file != null || this.m_inputStream != null) {
                try {
                    if (this.m_file != null) {
                        this.m_file.close();
                    }

                    if (this.m_inputStream != null) {
                        this.m_inputStream.close();
                    }
                } catch (IOException iOException) {
                    ExceptionLogger.logException(iOException);
                }

                this.m_file = null;
                this.m_inputStream = null;
                this.m_use_fallthrough = false;
            }
        }

        @Override
        public boolean read(byte[] _byte, long _long) {
            if (this.m_use_fallthrough) {
                return this.m_fallthrough.read(_byte, _long);
            } else if (this.m_file == null) {
                return false;
            } else {
                try {
                    return (long)this.m_file.read(_byte, 0, (int)_long) == _long;
                } catch (IOException iOException) {
                    ExceptionLogger.logException(iOException);
                    return false;
                }
            }
        }

        @Override
        public boolean write(byte[] _byte, long _long) {
            if (this.m_use_fallthrough) {
                return this.m_fallthrough.write(_byte, _long);
            } else if (this.m_file == null) {
                return false;
            } else {
                try {
                    this.m_file.write(_byte, 0, (int)_long);
                    return true;
                } catch (IOException iOException) {
                    ExceptionLogger.logException(iOException);
                    return false;
                }
            }
        }

        @Override
        public byte[] getBuffer() {
            return this.m_use_fallthrough ? this.m_fallthrough.getBuffer() : null;
        }

        @Override
        public long size() {
            if (this.m_use_fallthrough) {
                return this.m_fallthrough.size();
            } else if (this.m_file == null) {
                return 0L;
            } else {
                try {
                    return this.m_file.length();
                } catch (IOException iOException) {
                    ExceptionLogger.logException(iOException);
                    return 0L;
                }
            }
        }

        @Override
        public boolean seek(FileSeekMode fileSeekMode, long _long) {
            if (this.m_use_fallthrough) {
                return this.m_fallthrough.seek(fileSeekMode, _long);
            } else if (this.m_file == null) {
                return false;
            } else {
                try {
                    this.m_file.seek(switch (fileSeekMode) {
                        case CURRENT -> this.m_file.getFilePointer();
                        case END -> this.m_file.length();
                    });
                    return true;
                } catch (IOException iOException) {
                    ExceptionLogger.logException(iOException);
                    return false;
                }
            }
        }

        @Override
        public long pos() {
            if (this.m_use_fallthrough) {
                return this.m_fallthrough.pos();
            } else if (this.m_file == null) {
                return 0L;
            } else {
                try {
                    return this.m_file.getFilePointer();
                } catch (IOException iOException) {
                    ExceptionLogger.logException(iOException);
                    return 0L;
                }
            }
        }

        @Override
        public InputStream getInputStream() {
            return this.m_inputStream;
        }

        @Override
        public IFileDevice getDevice() {
            return this.m_device;
        }

        @Override
        public void release() {
            this.getDevice().destroyFile(this);
        }
    }
}
